/*
 * This file is part of aion-lightning <aion-lightning.org>.
 * 
 * aion-lightning is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * aion-lightning is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with aion-lightning.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.aionengine.gameserver.model.autogroup;

import com.aionengine.gameserver.model.gameobjects.player.Player;
import com.aionengine.gameserver.model.instance.instancereward.HarmonyArenaReward;
import com.aionengine.gameserver.model.instance.playerreward.HarmonyGroupReward;
import com.aionengine.gameserver.model.team2.TeamType;
import com.aionengine.gameserver.model.team2.group.PlayerGroup;
import com.aionengine.gameserver.model.team2.group.PlayerGroupService;
import com.aionengine.gameserver.network.aion.serverpackets.SM_AUTO_GROUP;
import com.aionengine.gameserver.services.AutoGroupService;
import com.aionengine.gameserver.utils.PacketSendUtility;
import com.aionengine.gameserver.world.WorldMapInstance;

import java.util.ArrayList;
import java.util.List;

/**
 * @author xTz
 */
public class AutoHarmonyInstance extends AutoInstance {

    private List<AGPlayer> group1 = new ArrayList<AGPlayer>();
    private List<AGPlayer> group2 = new ArrayList<AGPlayer>();

    @Override
    public void onInstanceCreate(WorldMapInstance instance) {
        super.onInstanceCreate(instance);
        HarmonyArenaReward reward = (HarmonyArenaReward) instance.getInstanceHandler().getInstanceReward();
        reward.addHarmonyGroup(new HarmonyGroupReward(0, 12000, (byte) 7, group1));
        reward.addHarmonyGroup(new HarmonyGroupReward(1, 12000, (byte) 7, group2));
    }

    @Override
    public AGQuestion addPlayer(Player player, SearchInstance searchInstance) {
        super.writeLock();
        try {
            if (!satisfyTime(searchInstance) || (players.size() >= agt.getPlayerSize())) {
                return AGQuestion.FAILED;
            }
            AGQuestion result;
            if (searchInstance.getEntryRequestType().isGroupEntry()) {
                result = canAddGroup(group1, player, searchInstance);
                if (result.isFailed()) {
                    result = canAddGroup(group2, player, searchInstance);
                }
                return result;
            }
            result = canAddPlayer(group1, player);
            if (result.isFailed()) {
                result = canAddPlayer(group2, player);
            }
            return result;
        } finally {
            super.writeUnlock();
        }
    }

    @Override
    public void onPressEnter(Player player) {
        super.onPressEnter(player);
        if (agt.isHarmonyArena()) {
            if (!decrease(player, 186000184, 1)) {
                players.remove(player.getObjectId());
                PacketSendUtility.sendPacket(player, new SM_AUTO_GROUP(instanceMaskId, 5));
                if (players.isEmpty()) {
                    AutoGroupService.getInstance().unRegisterInstance(instance.getInstanceId());
                }
                return;
            }
        }
        ((HarmonyArenaReward) instance.getInstanceHandler().getInstanceReward()).portToPosition(player);
        instance.register(player.getObjectId());
    }

    @Override
    public void onEnterInstance(Player player) {
        super.onEnterInstance(player);
        if (player.isInGroup2()) {
            return;
        }
        Integer object = player.getObjectId();
        List<AGPlayer> group = getGroup(object);
        if (group != null) {
            List<Player> _players = getPlayerFromGroup(group);
            _players.remove(player);
            if (_players.size() == 1 && !_players.get(0).isInGroup2()) {
                HarmonyArenaReward reward = (HarmonyArenaReward) instance.getInstanceHandler().getInstanceReward();
                HarmonyGroupReward r = reward.getHarmonyGroupReward(object);
                PlayerGroup newGroup = PlayerGroupService.createGroup(_players.get(0), player, TeamType.AUTO_GROUP, r.getId());
                int groupId = newGroup.getObjectId();
                if (!instance.isRegistered(groupId)) {
                    instance.register(groupId);
                }
            } else if (!_players.isEmpty() && _players.get(0).isInGroup2()) {
                PlayerGroupService.addPlayer(_players.get(0).getPlayerGroup2(), player);
            }
            if (!instance.isRegistered(object)) {
                instance.register(object);
            }
        }
    }

    @Override
    public void onLeaveInstance(Player player) {
        unregister(player);
        PlayerGroupService.removePlayer(player);
    }

    @Override
    public void unregister(Player player) {
        AGPlayer agp = players.get(player.getObjectId());
        if (agp != null) {
            if (group1.contains(agp)) {
                group1.remove(agp);
            } else if (group2.contains(agp)) {
                group2.remove(agp);
            }
        }
        super.unregister(player);
    }

    @Override
    public void clear() {
        super.clear();
        group1.clear();
        group2.clear();
    }

    private List<Player> getPlayerFromGroup(List<AGPlayer> group) {
        List<Player> _players = new ArrayList<Player>();
        for (AGPlayer agp : group) {
            for (Player p : instance.getPlayersInside()) {
                if (p.getObjectId().equals(agp.getObjectId())) {
                    _players.add(p);
                    break;
                }
            }
        }
        return _players;
    }

    private List<AGPlayer> getGroup(Integer obj) {
        AGPlayer agp = players.get(obj);
        if (agp != null) {
            if (group1.contains(agp)) {
                return group1;
            } else if (group2.contains(agp)) {
                return group2;
            }
        }
        return null;
    }

    private AGQuestion canAddGroup(List<AGPlayer> group, Player player, SearchInstance searchInstance) {
        if (group.size() > 0) {
            if (!group.get(0).getRace().equals(player.getRace())) {
                return AGQuestion.FAILED;
            }
        }
        if (group.size() + searchInstance.getMembers().size() <= 3) {
            for (Player member : player.getPlayerGroup2().getOnlineMembers()) {
                Integer obj = member.getObjectId();
                if (searchInstance.getMembers().contains(obj)) {
                    AGPlayer agp = new AGPlayer(member);
                    group.add(agp);
                    players.put(obj, agp);
                }
            }
            return instance != null ? AGQuestion.ADDED : (players.size() == agt.getPlayerSize() ? AGQuestion.READY : AGQuestion.ADDED);
        }
        return AGQuestion.FAILED;
    }

    private AGQuestion canAddPlayer(List<AGPlayer> group, Player player) {
        Integer obj = player.getObjectId();
        AGPlayer agp = new AGPlayer(player);
        if (group.size() < 3) {
            if (group.isEmpty()) {
                group.add(agp);
                players.put(obj, agp);
                return AGQuestion.ADDED;
            } else if (getAGPlayerByIndex(group, 0).getRace().equals(player.getRace())) {
                group.add(agp);
                players.put(obj, agp);
                return instance != null ? AGQuestion.ADDED : (players.size() == agt.getPlayerSize() ? AGQuestion.READY : AGQuestion.ADDED);
            }
        }
        return AGQuestion.FAILED;
    }

    private AGPlayer getAGPlayerByIndex(List<AGPlayer> group, int index) {
        return group.get(index);
    }

}
